package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.templates.AipFaceTemplate;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.dubbo.api.FriendApi;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.UserLikeApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 用户业务层
 */
@Service
public class UserService {

    @Reference
    private UserApi userApi;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private final String SMS_KEY = "SMS_KEY_"; // 定义验证码前缀

    private final String TOKEN_KEY = "TOKEN_KEY_"; // 定义token的前缀

    private final String FREEZE_KEY = "FREEZE_KEY_"; // 定义冻结状态的前缀

    @Value("${tanhua.secret}")
    private String secret; // 读取yml密钥

    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Reference
    private UserLikeApi userLikeApi;

    @Reference
    private FriendApi friendApi;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    /**
     * 保存用户
     *
     * @return
     */
    public ResponseEntity<Object> save(User user) {
        Long id = userApi.save(user);
        return ResponseEntity.ok(id);
    }

    /**
     * 根据手机号码查询用户
     *
     * @return
     */
    public ResponseEntity<Object> findByMobile(String mobile) {
        try {
            // 业务代码
            int i = 1 / 0;
            User user = userApi.findByMobile(mobile);
            return ResponseEntity.ok(user);

        } catch (Exception e) {
            // 定义错误内容
            Map<String, Object> result = new HashMap<>();
            result.put("errCode", "99999");
            result.put("errMsg", "对不起，我错了！");
            return ResponseEntity.status(500).body(result);
        }
    }

    /**
     * 登录第一步---手机号登录
     */
    public ResponseEntity<Object> login(String phone) {
        // 1.生成六位数随机验证码
        String code = (int) ((Math.random() * 9 + 1) * 100000) + "";

        code = "123456";

        // 2.调用阿里云短信发送验证码
        // smsTemplate.sendSms(phone, code);

        // 3.保存验证码到redis，并设置过期时间
        redisTemplate.opsForValue().set(SMS_KEY + phone, code, Duration.ofMinutes(2));

        return ResponseEntity.ok(null);
    }

    /**
     * 登录第二步---验证码校验
     */
    public ResponseEntity<Object> loginVerification(String phone, String verificationCode) {
        // 1.从redis取出验证码
        String redisCode = redisTemplate.opsForValue().get(SMS_KEY + phone);

        // 2.校验验证码
        if (StringUtils.isEmpty(redisCode) || !redisCode.equals(verificationCode)) {
            return ResponseEntity.status(500).body(ErrorResult.loginError());
        }

        // 3.验证通过后删除验证码
        redisTemplate.delete(SMS_KEY + phone);

        // 4.根据手机号码查询用户
        User user = userApi.findByMobile(phone);

        // 获取当前账号状态并判断是否冻结登录功能
        Boolean freeze = redisTemplate.hasKey(FREEZE_KEY + user.getId());
        UserInfo userInfo = userInfoApi.findById(user.getId());
        String freezingRange = userInfo.getFreezingRange();
        if (!(freeze && "1".equals(freezingRange)) ) {

            boolean isNew = false;

            String type = "0101"; // 登录
            if (user == null) {
                // 如果是新用户，自动注册
                user = new User();
                user.setMobile(phone);
                user.setPassword(DigestUtils.md5Hex("123456"));
                // user.setCreated(new Date());
                // user.setUpdated(new Date());
                // 【如果是新用户，注册完了后返回id】
                Long id = userApi.save(user);
                isNew = true;

                user.setId(id);

                // 【注册用户到环信】
                huanXinTemplate.register(id);

                type = "0102";
            }
            // 定义消息内容
            Map<String, Object> msg = new HashMap<>();
            msg.put("userId", user.getId());
            msg.put("type", type);
            msg.put("logTime", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

            if ("1".equals(freezingRange)){
                userInfo.setUserStatus("1");
                userInfo.setFreezingRange("0");
                userInfo.setFreezingTime("0");
                userInfoApi.update(userInfo);
            }

            // 【发送日志消息到RocketMQ】，参数1-主题:标签（相当于消息种类），参数2-消息内容，通常转成json字符串
            rocketMQTemplate.convertAndSend("tanhua-log", JSON.toJSONString(msg));


            // 【加密得到token】
            String token = JwtUtils.createToken(user.getId(), phone, secret);

            // 【将用户信息转为json字符串】
            String tokenData = JSON.toJSONString(user);

            // 【将token存入redis，并设置4小时过期时间，当用户4小时没有做任何操作时，自动退出登录】
            redisTemplate.opsForValue().set(TOKEN_KEY + token, tokenData, Duration.ofHours(4));


            // 5.封装返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("token", token);
            result.put("isNew", isNew);

            return ResponseEntity.ok(result);
        }

        return ResponseEntity.status(401).body("账号已被冻结，请联系管理员");
    }

    /**
     * 新用户---1填写资料
     */
    public ResponseEntity<Object> saveUserInfo(UserInfo userInfo) {
        // 获取当前登录用户信息
        User user = UserHolder.get();

        // 2.设置用户详情id
        userInfo.setId(user.getId());

        // 设置账号状态 1:正常 2:冻结
        userInfo.setUserStatus("1");
        userInfo.setFreezingRange("0");
        userInfo.setFreezingTime("0");

        // 3.调用服务提供者api保存用户详情
        userInfoApi.save(userInfo);

        return ResponseEntity.ok(null);
    }

    /**
     * 根据token获取用户信息
     *
     * @param token
     * @return
     */
    public User findUserByToken(String token) {
        // 获取用户的json字符串信息
        String userJsonData = redisTemplate.opsForValue().get(TOKEN_KEY + token);

        if (StringUtils.isEmpty(userJsonData)) {
            return null;
        }

        // 将用户json转为对象
        User user = JSON.parseObject(userJsonData, User.class);

        // 将token过期时间重置
        redisTemplate.opsForValue().set(TOKEN_KEY + token, userJsonData, Duration.ofHours(4));

        return user;
    }

    /**
     * 新用户---2选取头像
     */
    public ResponseEntity<Object> updateUserHead(MultipartFile headPhoto) throws Exception {
        // 获取当前登录用户信息
        User user = UserHolder.get();

        // 2.人脸检测
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect) {
            // 如果非人脸，直接返回
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }

        // 3.上传头像到阿里云OSS
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        // 4.调用服务提供者api更新头像到用户详情表
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(url);
        userInfoApi.update(userInfo);


        return ResponseEntity.ok(null);
    }

    /**
     * 用户资料 - 读取
     */
    public ResponseEntity<Object> findUserInfoById() {

        // 2.调用服务提供者api查询用户详情
        UserInfo userInfo = userInfoApi.findById(UserHolder.getUserId());

        // 3.封装返回结果，UserInfoVo
        UserInfoVo vo = new UserInfoVo();

        if (userInfo != null) {
            // 对象拷贝，参数1-源对象，参数2-目标对象，自动将属性名且类型一样的属性进行赋值
            BeanUtils.copyProperties(userInfo, vo);
            // 设置年龄
            if (userInfo.getAge() != null) {
                vo.setAge(userInfo.getAge().toString());
            }
        }
        return ResponseEntity.ok(vo);
    }

    /**
     * 用户资料 - 保存
     */
    public ResponseEntity<Object> updateUserInfo(UserInfo userInfo) {

        // 2.设置用户id
        userInfo.setId(UserHolder.getUserId());

        // 3.调用服务提供者api更新用户详情
        userInfoApi.update(userInfo);

        return ResponseEntity.ok(null);
    }

    /**
     * 修改手机号 - 2 校验验证码
     */
    public ResponseEntity<Object> checkVerificationCode(String code) {
        // 1.获取用户信息
        User user = UserHolder.get();

        // 2.从redis中获取验证码
        String key = SMS_KEY + user.getMobile();
        String redisCode = redisTemplate.opsForValue().get(key);

        // 3.判断
        Boolean verification = true;
        if (code == null || redisCode == null || !redisCode.equals(code)) {
            // 3.1 校验失败
            verification = false;
        } else {
            // 3.2 校验成功，从redis中删除验证码
            redisTemplate.delete(key);
        }

        // 4.构造返回结果:{"verification":false/true}
        Map<String, Boolean> resultMap = new HashMap<>();
        resultMap.put("verification", verification);

        return ResponseEntity.ok(resultMap);
    }

    /**
     * 修改手机号 - 3 保存
     *
     * @param phone 修改后的手机号
     * @return
     */
    public ResponseEntity<Object> updateUserPhone(String phone) {
        // 1.根据修改后的手机号码查询，如果手机号码已经存在返回错误信息
        User user = userApi.findByMobile(phone);
        if (user != null) {
            return ResponseEntity.status(500).body(ErrorResult.mobileError());
        }

        // 2.获取用户信息、设置修改手机号
        User updateUser = UserHolder.get();
        updateUser.setMobile(phone);

        // 3.修改用户
        userApi.update(updateUser);
        return ResponseEntity.ok(null);
    }

    /**
     * 互相喜欢，喜欢，粉丝 - 统计
     */
    public ResponseEntity<Object> queryCounts() {
        // 1.查询当前登录用户id
        Long userId = UserHolder.getUserId();

        // 2.分别查询互相关注数、喜欢数、粉丝数
        Long eachLoveCount = userLikeApi.queryEachLoveCount(userId);
        Long loveCount = userLikeApi.queryLoveCount(userId);
        Long fanCount = userLikeApi.queryFansCount(userId);

        // 3.封装返回结果
        Map<String, Integer> result = new HashMap<>();
        result.put("eachLoveCount", eachLoveCount.intValue());
        result.put("loveCount", loveCount.intValue());
        result.put("fanCount", fanCount.intValue());

        return ResponseEntity.ok(result);
    }

    /**
     * 互相喜欢、喜欢、粉丝、谁看过我 - 翻页列表
     */
    public ResponseEntity<Object> queryUserLikeList(Integer type, Integer page, Integer pagesize) {
        // 1.获取当前登录用户id
        Long userId = UserHolder.getUserId();

        // 2.分页查询各种列表数据
        PageResult pageResult = null;
        switch (type) {

            case 1:
                // 互相关注列表
                pageResult = userLikeApi.queryEachLoveList(userId, page, pagesize);
                break;
            case 2:
                // 喜欢列表
                pageResult = userLikeApi.queryLoveList(userId, page, pagesize);
                break;
            case 3:
                // 粉丝列表
                pageResult = userLikeApi.queryFansList(userId, page, pagesize);
                break;
            case 4:
                // 谁看过我列表
                pageResult = userLikeApi.queryVisitorsList(userId, page, pagesize);
                break;
        }
        return ResponseEntity.ok(pageResult);
    }

    /**
     * 粉丝 - 喜欢
     */
    public ResponseEntity<Object> fansLike(Long fanId) {
        // 1.移除粉丝数据
        userLikeApi.delete(UserHolder.getUserId(), fanId);

        // 2.添加好友双向关系
        friendApi.save(UserHolder.getUserId(), fanId);

        // 3.注册好友关系到环信
        huanXinTemplate.contactUsers(UserHolder.getUserId(), fanId);

        return ResponseEntity.ok(null);
    }
}
